package com.example.api.common.Security;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import java.util.Date;
import java.util.Map;

public class JwtTokenUtil {

    // 提供一个对外使用的常量，方便在其他地方调用
    public static final String USER_INFO_USERNAME = JwtConstant.USER_INFO_USERNAME;

    /**
     * 根据传入的 claims 生成 token
     */
    public static String createToken(Map<String, Object> claims) {
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(generateExpirationDate())
                .signWith(Keys.hmacShaKeyFor(Decoders.BASE64.decode(JwtConstant.JWT_SECRET)))
                .compact();
    }

    /**
     * 解析 token 并返回 claims
     */
    public static Claims parseToken(String token) {
        try {
            return Jwts.parserBuilder()
                    .setSigningKey(Decoders.BASE64.decode(JwtConstant.JWT_SECRET))
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 生成 token 过期时间
     */
    private static Date generateExpirationDate() {
        return new Date(System.currentTimeMillis() + JwtConstant.JWT_EXPIRATION);
    }

    /**
     * 从 token 中提取用户名
     */
    public static String getUserName(String token) {
        Claims claims = parseToken(token);
        return claims != null ? claims.get(USER_INFO_USERNAME, String.class) : null;
    }

    /**
     * 验证 token 是否有效
     */
    public static boolean validateToken(String token) {
        Claims claims = parseToken(token);
        return claims != null && !isTokenExpired(token);
    }

    /**
     * 判断 token 是否已经过期
     */
    public static boolean isTokenExpired(String token) {
        Date expireDate = getExpiredDate(token);
        return expireDate.before(new Date());
    }

    private static Date getExpiredDate(String token) {
        Claims claims = parseToken(token);
        return claims != null ? claims.getExpiration() : new Date(0);
    }

    /**
     * 刷新 token
     */
    public static String refreshToken(String token) {
        Claims claims = parseToken(token);
        if (claims != null) {
            claims.put(JwtConstant.JWT_CREATE_TIME, new Date());
            return createToken(claims);
        }
        return null;
    }
}
